package org.zachary.imitation.raft;

import java.io.Serializable;

/**
 * 封装节点所属的 group（集群 ID）以及节点自身的信息，集群 ID 以及节点自身信息就可以唯一确定一个节点。
 *
 *  假设业务数据是 20000 条键值对的 Map，put(a, 1) 和 put(b, 2) 这两条指令实际上是毫无关系的，可以并行地生成日志对象并复制到其它节点。由于日志的索引是递增的，所以日志就是有顺序的，这样一来，指令的执行也就有了顺序。
 * 两个毫无关系的指令 put(a, 1) 和 put(b, 2) 就只能串行执行了，即便它们互不干扰。按理说这两条指令完全可以并发执行，不必考虑顺序关系。客户端 1 指令执行的时候，客户端 2 的指令也可以同时执行。但没办法，按照 raft 算法的要求，这两条客户端
 * 指令都会被包装成日志，都在同一个日志系统里面，就只能按照先后顺序来执行。
 *
 * 之所以无法并发执行是因为这两条指令包装成日志之后，都会在同一个日志系统里按照日志索引顺序等待应用。如果这两条指令被包装成日志之后，并不在同一个日志系统中就可以并行执行了。客户端 1 操作的数据在第一个日志系统中，客户端 2 操纵的数据在第二个日志系统中，
 * 这样一来，操纵这两条数据的指令就可以并发执行了。一个 raft 集群对应一个日志系统，两个 raft 集群自然就会对应两个日志系统。现在，假设有 3 个节点，node1、node2、node3 组成 cluster1，同样地，node1、node2、node3 组成第二个集群 cluster2，并且它们同一个进程中。
 *
 * 这样，每一个服务器不再部署一个 raft 节点了，而是部署了两个 raft 节点，并且这两个节点是由同一个进程启动的。通过这种方式可以实现并行执行。实际上，这就是一个非常简单的 Multi-Raft Group 例子。
 *
 * 同一个节点（ip:port），分属于两个不同的集群，如何区分它们呢？实际上，它们的 group（所属组，亦即 clusterId） 是不一样的。在 Leader 向 Follower 发送信息的时候，都会把目标节点的 group/clusterId 封装在请求当中，这样，当目标服务器接收到请求之后，
 * 会根据请求中的 group/clusterId，把请求转发给正确的节点。
 *
 * 因此，这里引入 {@link NodeId} 类，这个类封装了 group（集群 Id）和节点自身的信息。所以，当一个服务器中的同一个进程部署了多个 raft 节点，就可以使用 NodeId 对象来区分每一个节点。
 *
 * Created by guozhaokun on 2024/8/30 20:20.
 */
public class NodeId implements Serializable {

	/** 当前节点所属的组，具有相同 group 的 Node 组成了一个集群。group 也可以理解为集群 ID */
	private String groupId;
	/** 当前节点自己的节点信息 */
	private PeerId peerId;

	public NodeId(String groupId, PeerId peerId) {
		this.groupId = groupId;
		this.peerId = peerId;
	}

	public String getGroupId() {
		return groupId;
	}

	public void setGroupId(String groupId) {
		this.groupId = groupId;
	}

	public PeerId getPeerId() {
		return peerId;
	}

	public void setPeerId(PeerId peerId) {
		this.peerId = peerId;
	}
}
